import * as XLSX from 'xlsx';
import * as Papa from 'papaparse';
import { ConvertOptions, ConvertResult } from '../types';
import { logger } from './logger';

export class CsvConverter {
  /**
   * 将CSV数据转换为XLSX格式
   * @param csvData CSV字符串数据
   * @param options 转换选项
   * @returns 转换结果
   */
  static async convertToXlsx(csvData: string, options: ConvertOptions): Promise<ConvertResult> {
    const startTime = Date.now();
    logger.info('开始CSV到XLSX转换', { 
      dataLength: csvData.length,
      options 
    });

    try {
      // 解析CSV数据
      logger.info('开始解析CSV数据');
      const parsedData = this.parseCsv(csvData, options);
      logger.info('CSV数据解析完成', { 
        rowCount: parsedData.data.length,
        columnCount: parsedData.data[0]?.length || 0 
      });
      
      // 创建工作簿和工作表
      logger.info('创建工作簿和工作表');
      const workbook = XLSX.utils.book_new();
      
      // 将对象数组转换为二维数组格式
      let dataArray: any[][];
      
      if (options.hasHeader !== false && parsedData.data.length > 0 && typeof parsedData.data[0] === 'object') {
        // 对象数组格式，需要转换为二维数组
        const headers = Object.keys(parsedData.data[0]);
        dataArray = [headers]; // 表头行
        
        // 数据行
        for (const row of parsedData.data) {
          dataArray.push(headers.map(header => row[header]));
        }
      } else {
        // 已经是二维数组格式
        dataArray = parsedData.data as any[][];
      }
      
      const worksheet = XLSX.utils.aoa_to_sheet(dataArray);
      
      // 添加工作表到工作簿
      const sheetName = options.sheetName || 'Sheet1';
      XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
      logger.info('工作表添加到工作簿', { sheetName });
      
      // 生成XLSX文件Buffer
      logger.info('生成XLSX文件Buffer');
      const xlsxBuffer = XLSX.write(workbook, { 
        type: 'buffer', 
        bookType: 'xlsx',
        compression: true
      });
      
      const endTime = Date.now();
      logger.info('CSV到XLSX转换成功', { 
        duration: `${endTime - startTime}ms`,
        outputSize: xlsxBuffer.length,
        sheetName 
      });
      
      return {
        success: true,
        data: xlsxBuffer,
        outputPath: ''
      };
      
    } catch (error) {
      const endTime = Date.now();
      logger.error('CSV到XLSX转换失败', error as Error, { 
        duration: `${endTime - startTime}ms`,
        options 
      });
      
      return {
        success: false,
        error: error instanceof Error ? error.message : 'Unknown error occurred'
      };
    }
  }

  /**
   * 解析CSV数据
   * @param csvData CSV字符串
   * @param options 解析选项
   * @returns 解析后的数据
   */
  private static parseCsv(csvData: string, options: ConvertOptions): any {
    const startTime = Date.now();
    logger.debug('开始解析CSV数据', {
      dataLength: csvData.length,
      options
    });

    const config = {
      delimiter: options.delimiter || ',',
      header: false, // 强制不使用header，确保返回二维数组
      skipEmptyLines: true,
      encoding: options.encoding || 'UTF-8',
      transform: (value: string) => {
        // 尝试转换数字和布尔值
        if (!isNaN(Number(value)) && value.trim() !== '') {
          return Number(value);
        }
        if (value.toLowerCase() === 'true') return true;
        if (value.toLowerCase() === 'false') return false;
        return value;
      }
    };

    try {
      const result = Papa.parse(csvData, config);
      
      if (result.errors.length > 0) {
        logger.warn('CSV解析出现警告', {
          errors: result.errors,
          dataSample: csvData.substring(0, 100) + '...'
        });
      }

      const endTime = Date.now();
      logger.debug('CSV解析完成', {
        duration: `${endTime - startTime}ms`,
        rowCount: result.data.length,
        errorCount: result.errors.length,
        hasHeader: config.header
      });

      return result;
      
    } catch (error) {
      const endTime = Date.now();
      logger.error('CSV解析失败', error as Error, {
        duration: `${endTime - startTime}ms`,
        delimiter: config.delimiter,
        encoding: config.encoding
      });
      throw error;
    }
  }

  /**
   * 验证CSV数据格式
   * @param csvData CSV字符串
   * @returns 是否有效
   */
  static validateCsv(csvData: string): boolean {
    const startTime = Date.now();
    logger.debug('开始验证CSV数据格式');

    if (!csvData || typeof csvData !== 'string') {
      logger.warn('CSV数据验证失败: 数据为空或不是字符串');
      return false;
    }

    // 简单的CSV格式验证
    const lines = csvData.split('\n');
    if (lines.length < 1) {
      logger.warn('CSV数据验证失败: 数据行数不足');
      return false;
    }

    // 检查是否包含分隔符（逗号、分号或制表符）
    const firstLine = lines[0];
    const hasDelimiter = /[,;\t]/.test(firstLine);
    
    const endTime = Date.now();
    logger.debug('CSV数据验证完成', {
      duration: `${endTime - startTime}ms`,
      isValid: hasDelimiter,
      lineCount: lines.length,
      firstLineSample: firstLine.substring(0, 50) + (firstLine.length > 50 ? '...' : '')
    });
    
    return hasDelimiter;
  }

  /**
   * 获取CSV文件的预览数据（前10行）
   * @param csvData CSV字符串
   * @param options 解析选项
   * @returns 预览数据
   */
  static getPreview(csvData: string, options: ConvertOptions): any[][] {
    const lines = csvData.split('\n').slice(0, 11); // 获取前10行数据+表头
    const previewData = lines.join('\n');
    
    const result = this.parseCsv(previewData, options);
    return result.data;
  }

  /**
   * 检测CSV文件的编码格式
   * @param buffer 文件Buffer
   * @returns 编码格式
   */
  static detectEncoding(buffer: Buffer): string {
    const startTime = Date.now();
    logger.debug('开始检测文件编码', {
      bufferSize: buffer.length
    });

    // 简单的编码检测逻辑
    const text = buffer.toString('binary');
    
    // 检测UTF-8 BOM
    if (buffer.length >= 3 && 
        buffer[0] === 0xEF && 
        buffer[1] === 0xBB && 
        buffer[2] === 0xBF) {
      const endTime = Date.now();
      logger.debug('检测到UTF-8 BOM编码', {
        duration: `${endTime - startTime}ms`,
        encoding: 'UTF-8'
      });
      return 'UTF-8';
    }
    
    // 检测GBK编码（中文环境常见）
    // 这里使用简单的启发式方法
    try {
      const utf8Text = buffer.toString('utf8');
      // 如果UTF-8解码没有抛出错误，可能是UTF-8
      const endTime = Date.now();
      logger.debug('检测到UTF-8编码', {
        duration: `${endTime - startTime}ms`,
        encoding: 'UTF-8'
      });
      return 'UTF-8';
    } catch {
      // 如果UTF-8解码失败，尝试GBK
      const endTime = Date.now();
      logger.debug('检测到GBK编码', {
        duration: `${endTime - startTime}ms`,
        encoding: 'GBK'
      });
      return 'GBK';
    }
  }
}